<script setup>
import { ref,inject,onMounted,useTemplateRef } from 'vue'
import { useRoute} from 'vue-router'
import { marked } from 'marked'

const route = useRoute()
const options = inject('options')
const modelName = route.params.modelName
const messageInput=ref("")
const talkEnable=ref(true)
const messagePanel = useTemplateRef('messagePanel')

const chatData=ref({
  model: modelName,
  stream: true,
  messages: []
})

function scrollBottom() {
  messagePanel.value.scrollTo(0, messagePanel.value.scrollHeight);
}

function splitEvent(str) {
  const jsonObjects = [];
  let startIndex = 0;
  let braceCount = 0;
  let inString = false;
  let escapeChar = false;

  for (let i = 0; i < str.length; i++) {
    const char = str[i];

    if (char === '{' && !inString) {
      if (braceCount === 0) {
        startIndex = i;
      }
      braceCount++;
    } else if (char === '}' && !inString) {
      braceCount--;
      if (braceCount === 0) {
        const jsonString = str.substring(startIndex, i + 1);
        try {
          const jsonObject = JSON.parse(jsonString);
          jsonObjects.push(jsonObject);
        } catch (error) {
          console.error("Error parsing JSON:", error);
        }
      }
    } else if (char === '"' && !escapeChar) {
      inString = !inString;
    }

    if (char === '\\') {
      escapeChar = !escapeChar;
    } else {
      escapeChar = false;
    }
  }

  return jsonObjects;
}

function userTalk(msg)
{
  chatData.value.messages.push({
    role: 'user',
    content: msg
  })
  talkEnable.value=false;
  messageInput.value="";
  fetch(options.value.baseUrl+'/api/chat',{
    method: "POST",
    headers: {"Content-Type":"application/json" },
    body: JSON.stringify(chatData.value) 
  })
  .then((response) => {
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    
    chatData.value.messages.push({
      role: 'assistant',
      content: '',
      done: false
    })

    var aiTalk=chatData.value.messages[chatData.value.messages.length-1];
    const reader = response.body.getReader();
    const stream = new ReadableStream({
      start(controller) {
        function push() {
          reader.read().then(({ done, value }) => {
            if (done) {
              controller.close();
              return;
            }
            // 将二进制数据转换为文本
            const decoder = new TextDecoder("utf-8")
            const chunk = decoder.decode(value, { stream: true })
            // 处理接收到的文本数据
            //console.log("Received chunk:", chunk)
            const es=splitEvent(chunk);
            es.forEach(e=>{
              aiTalk.content+=e.message.content
            })
            if(es[es.length-1].done) aiTalk.done=true
            scrollBottom()
            // 继续读取下一个数据块
            controller.enqueue(value)
            push()
          })
        }
        push()
      },
    });
    //return new Response(stream).text();
  })
  .then((data) => {
    console.log("All data received!");
    talkEnable.value=true;
  })
  .catch((error) => {
    console.error("Fetch error:", error);
    talkEnable.value=true;
  });
}
onMounted(()=>{
  userTalk('hello')
})
</script>

<template>
  <el-container>
    <el-aside width="200px">
      <h3 style="padding:10px;margin:0px;">{{modelName}}</h3>
    </el-aside>
    <el-main class="border">
      <div class="message_panel" ref="messagePanel">
        <div v-for="message in chatData.messages">
          <div v-if="message.role=='assistant'" class="talk_ai" >
            <div v-html="marked.parse(message.content)"></div>
          </div>
          <div v-else class="talk_user">
            <div v-html="marked.parse(message.content)"></div>
          </div>
        </div>
      </div>
      <div class="message_input">
        <el-input :enable="talkEnable" v-model="messageInput" :rows="2" type="textarea" placeholder="请输入内容" @keyup.enter.ctrl="userTalk(messageInput)"></el-input>
        <el-button :enable="talkEnable" type="primary" @click="userTalk(messageInput)">发送</el-button>
      </div>
    </el-main>
  </el-container>
</template>

<style scoped>
.el-container {
  height: 100%;
}
.el-main {
  height: 100%;
}
.el-aside { 
  padding: 0;
  margin: 0;
}
div.talk_ai {
  background-color: white;
  text-align: left;
  width: 80%;
  margin: 0 0 10px 0;
  border: solid 1px #ccc;
  border-radius: 10px;
  box-shadow: #ccc 0px 0px 5px;
  padding: 10px;
}
div.talk_user {
  background-color: white;
  margin: 0 0 10px 20%;
  text-align: right;
  border: solid 1px #ccc;
  border-radius: 10px;
  box-shadow: #ccc 0px 0px 5px;
  padding: 10px;
}
div.message_panel {
  
  background-color: rgb(235.9, 245.3, 255);
  height:calc(100% - 90px);
  overflow-y: auto;
  padding: 10px;
  margin-bottom: 10px;
  border: solid 1px #ccc;
}
div.message_input {
  display: flex;
  gap: 10px;
}

</style>
